# -*- coding: UTF-8 -*-

from __future__ import with_statement

import sys
import urllib2

import glib

import gconf_client

    #
    # This is called Thread due to historical reasons
    #
class UrlThread(object):
        #
        # We should not try to connect immediately after
        # NetworkManager told us that network is available.
        # Wait for this amount of time.
        #
    __CONNECTION_WAIT_INTERVAL = 5 # seconds

    __XML_DATA = (('<karma>', '</karma>'),
                  ('<rating>', '</rating>'),
                  ('<ratingPosition>', '</ratingPosition>'))

    # Initialization

    def __init__(self, gconf, nm_observee):
        super(UrlThread, self).__init__()
        self.__gconf = gconf

            #
            # Identifier of GTK callback running with user-defined interval
            #
        self.__cb_id = None
            #
            # Identifier of GTK callback that runs once
            # with interval equal to __CONNECTION_WAIT_INTERVAL
            #
        self.__cb2_id = None

        self.__observers = []

        def nm_observer(nm_observee):
            self.start(delay=True) if nm_observee.connected else self.stop()
        nm_observee.attach(nm_observer)

        def nickChanged(setting):
            self.__gconf.karma.reset()
            self.__gconf.habrapower.reset()
            self.__gconf.rating.reset()
            if self.enabled():
                self.update()
        self.__gconf.nick.attach(nickChanged, notify_now=False)

        proxies = None if not gconf.http_proxy else {'http': gconf.http_proxy}
        urllib2.install_opener(urllib2.build_opener(urllib2.ProxyHandler(proxies)))

    # Observee

    class AttemptObserver:
        def success(self, thread):
            pass
        def failure(self, thread, error):
            pass

    def attach(self, observer):
        if not observer in self.__observers:
            self.__observers.append(observer)

    def detach(self, observer):
        try:
            self.__observers.remove(observer)
        except ValueError:
            pass

    def notify_success(self, *args, **kwargs):
        for observer in self.__observers:
            observer.success(self, *args, **kwargs)

    def notify_failure(self, *args, **kwargs):
        for observer in self.__observers:
            observer.failure(self, *args, **kwargs)

    # General methods

    def started(self):
        return self.__cb2_id is not None or self.__cb_id is not None

    def start(self, delay=False):
        if self.__cb2_id is None:
            self.stop()
            if delay:
                self.__cb2_id = glib.timeout_add_seconds(self.__CONNECTION_WAIT_INTERVAL, self.__cb2)
            else:
                self.__cb()
                self.__cb_id = glib.timeout_add_seconds(self.__gconf.refreshInterval.value() * 60, self.__cb)

    def stop(self):
        if self.__cb2_id is not None:
            glib.source_remove(self.__cb2_id)
            self.__cb2_id = None
        if self.__cb_id is not None:
            glib.source_remove(self.__cb_id)
            self.__cb_id = None


    def enabled(self):
        return self.started()

    def update(self):
        return self.start()

    # Helper methods

    def __cb(self):
        #
        # GTK callback running with user-defined interval.
        # Its identifiers is stored in self.__cb_id.
        # Always return True to let GTK continue running this callback
        # (until it is explicitely stopped).
        #

        url = 'http://habrahabr.ru/api/profile/' + self.__gconf.nick.value()

        print >> sys.stderr, _('Update')

        error = None
        results = []
        try:
            d = self.__XML_DATA[0]
            f = urllib2.urlopen(url)
            try:
                for line in f:
                    p = line.find(d[0])
                    if p == -1:
                        continue
                    p += len(d[0])

                    p2 = line.find(d[1], p)
                    if p2 == -1:
                        continue

                    results.append(line[p:p2])
                    if len(results) == len(self.__XML_DATA):
                        break;
                    d = self.__XML_DATA[len(results)]
            finally:
                f.close()
        except IOError:
            error = _('Failed to connect to %s') % url

        if error is None:
            if len(results) != len(self.__XML_DATA):
                error = _('Failed to parse %s') % url
            else:
                try:
                    karma = float(results[0])
                    habrapower = float(results[1])
                    rating = int(results[2])
                except ValueError:
                    error = _('Failed to parse %s') % url
                else:
                    self.__gconf.karma.set(karma)
                    self.__gconf.habrapower.set(habrapower)
                    self.__gconf.rating.set(rating)
                    self.notify_success()

        if error is not None:
            print >> sys.stderr, error
            self.notify_failure(error)

        return True

    def __cb2(self):
        #
        # GTK callback that runs once with interval equal to __CONNECTION_WAIT_INTERVAL.
        # Its identifiers is stored in self.__cb2_id.
        # Always return False to tell GTK that it must not call this callback
        # any more (until it is explicitly set).
        #
        self.__cb2_id = None
        self.start()
        return False
